import React from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import { useEffect, useMemo } from 'react';
import routes from './route';
import RouterAuth from './RouterAuth';
import { useDispatchMenu, useStateMenuList, useStateBackRoute } from '/@/store/hooks/menu';
import { MenuItem } from '../types/menu';
import Load from '../components/asyncComponent';
import KeepAlive from 'react-activation';
// 后端控制路由，动态导入组件
const layouModules: any = import.meta.glob('../Layouts/*.{jsx,tsx}');
const pageModules: any = import.meta.glob('../page/**/*.{jsx,tsx}');
const viewsModules: any = import.meta.glob('../views/**/*.{jsx,tsx}');
/**
 * 获取目录下的 .jsx、.tsx 全部文件
 * @method import.meta.glob
 * @link 参考：https://cn.vitejs.dev/guide/features.html#json
 */
const dynamicViewsModules: Record<string, Function> = Object.assign(
  {},
  { ...layouModules },
  { ...viewsModules },
  { ...pageModules }
);
//处理引入组件
const lazyLoad = (moduleName: string) => {
  const Module = Load(dynamicImport(dynamicViewsModules, `${moduleName}`));
  return <Module />;
};

/**
 * 后端路由 component 转换函数
 * @param dynamicViewsModules 获取目录下的 .jsx、.tsx 全部文件
 * @param component 当前要处理项 component
 * @returns 返回处理成函数后的 component
 */
function dynamicImport(dynamicViewsModules: Record<string, Function>, component: string) {
  const keys = Object.keys(dynamicViewsModules);
  const matchKeys = keys.filter((key) => {
    const k = key.replace(/..\/views|../, '');
    return k.startsWith(`${component}`) || k.startsWith(`/${component}`);
  });
  if (matchKeys?.length === 1) {
    const matchKey = matchKeys[0];
    return dynamicViewsModules[matchKey];
  }
  if (matchKeys?.length > 1) {
    return false;
  }
}

//转换组件
const transFormComponent = (Component: any) => {
  //如果是一个url地址组件进行动态导入
  if (typeof Component === 'string' || Component === 'undefined') {
    return lazyLoad(Component && Component);
  }
  //如果是函数import('/@/xxx.vue'))导入进行转换成组件
  if (typeof Component === 'function') {
    return <Component></Component>;
  }
  //如果是import xx from '/@/xx'导入直接返回
  return Component;
};
export default function RouterView() {
  //提交Dispatch更新路由
  const { stateSetMenuList } = useDispatchMenu();
  const backList = useStateBackRoute();
  //获取redux中的路由信息
  const routerList: MenuItem[] = useStateMenuList();
  //初始化redux中的路由信息
  useEffect(() => {
    const HOEMITEM = routes.find((item) => item.path === '/');
    HOEMITEM?.children?.push(...backList);
    stateSetMenuList(routes);
  }, [stateSetMenuList, useStateBackRoute]);

  //路由中的element
  const Routerelement = (item: MenuItem) => {
    //包装高阶返回， item.roles☞route中的配置的权限信息,没有返回403
    if (item.roles && item.roles.length > 0) {
      return (
        <RouterAuth
          component={transFormComponent(item.element)}
          requiredRoles={item.roles}
          redirectTo='/login'
          isAuthMenu={item?.isAuthMenu ?? (true as boolean)}
        />
      );
    }
    return item.element && transFormComponent(item.element);
  };
  //渲染路由
  const RouterTree = (RouterArr: MenuItem[]): React.ReactNode => {
    return (
      RouterArr &&
      RouterArr.map((item) => {
        if (item.children === undefined) {
          if (item.redirect !== undefined) {
            return <Route path={item.path} element={<Navigate to={item.redirect} />} key={item.path} />;
          }
          return item.cache ? (
            <Route
              path={item.path}
              element={
                <KeepAlive id={item.path} saveScrollPosition='screen'>
                  {Routerelement(item)}
                </KeepAlive>
              }
              key={item.path}
            />
          ) : (
            <Route path={item.path} element={Routerelement(item)} key={item.path} />
          );
        }
        return (
          <Route path={item.path} element={Routerelement(item)} key={item.path}>
            {item.children && RouterTree(item.children)}
          </Route>
        );
      })
    );
  };

  const elements: React.ReactNode = useMemo(() => RouterTree(routerList), [routerList]);
  return (
    <>
      <Routes> {elements}</Routes>
    </>
  );
}
